home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / trace.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  9KB  |  381 lines

  1. /* Packet tracing - top level and generic routines, including hex/ascii
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  
  5. /****************************************************************************
  6. *    $Id: trace.c 1.2 93/07/16 11:51:47 ROOT_DOS Exp $
  7. *    15 Jul 93    1.2        GT    Fix warnings.                                    *
  8. *
  9. *  ATARI Version by David Nash - dnash@chaos.demon.co.uk
  10. *
  11. ****************************************************************************/
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <time.h>
  16. #include "global.h"
  17. #ifdef    ANSIPROTO
  18. #include <stdarg.h>
  19. #endif
  20. #include "mbuf.h"
  21. #include "iface.h"
  22. #include "pktdrvr.h"
  23. #include "commands.h"
  24. #include "trace.h"
  25. #include "ip.h"
  26.  
  27. static void ascii_dump __ARGS((FILE *fp,struct mbuf **bpp));
  28. static void ctohex __ARGS((char *buf,int16 c));
  29. static void fmtline __ARGS((FILE *fp,int16 addr,char *buf,int16 len));
  30. static void hex_dump __ARGS((FILE *fp,struct mbuf **bpp));
  31. static void showtrace __ARGS((struct iface *ifp));
  32.  
  33. /* Redefined here so that programs calling dump in the library won't pull
  34.  * in the rest of the package
  35.  */
  36. static char nospace[] = "No space!!\n";
  37.  
  38. struct tracecmd Tracecmd[] = {
  39.     { "input",    IF_TRACE_IN,    IF_TRACE_IN },
  40.     { "-input",    0,        IF_TRACE_IN },
  41.     { "output",    IF_TRACE_OUT,    IF_TRACE_OUT },
  42.     { "-output",    0,        IF_TRACE_OUT },
  43.     { "broadcast",    0,        IF_TRACE_NOBC },
  44.     { "-broadcast",    IF_TRACE_NOBC,    IF_TRACE_NOBC },
  45.     { "raw",        IF_TRACE_RAW,    IF_TRACE_RAW },
  46.     { "-raw",        0,        IF_TRACE_RAW },
  47.     { "ascii",    IF_TRACE_ASCII,    IF_TRACE_ASCII|IF_TRACE_HEX },
  48.     { "-ascii",    0,        IF_TRACE_ASCII|IF_TRACE_HEX },
  49.     { "hex",        IF_TRACE_HEX,    IF_TRACE_ASCII|IF_TRACE_HEX },
  50.     { "-hex",        IF_TRACE_ASCII,    IF_TRACE_ASCII|IF_TRACE_HEX },
  51.     { "off",        0,        0xffff },
  52.     { NULLCHAR,    0,        0 }
  53. };
  54.  
  55.  
  56. void
  57. dump(ifp,direction,type,bp)
  58. register struct iface *ifp;
  59. int direction;
  60. unsigned type;
  61. struct mbuf *bp;
  62. {
  63.     struct mbuf *tbp;
  64.     void (*func) __ARGS((FILE *,struct mbuf **,int));
  65.     int16 size;
  66.     time_t timer;
  67.     char *cp;
  68.  
  69.     if(ifp == NULL || (ifp->trace & direction) == 0)
  70.         return;    /* Nothing to trace */
  71.  
  72.     switch(direction){
  73.     case IF_TRACE_IN:
  74.         if((ifp->trace & IF_TRACE_NOBC)
  75.          && (Tracef[type].addrtest != NULLFP)
  76.          && (*Tracef[type].addrtest)(ifp,bp) == 0)
  77.             return;        /* broadcasts are suppressed */
  78.         time(&timer);
  79.         cp = ctime(&timer);
  80.         cp[24] = '\0';
  81.         fprintf(ifp->trfp,"\n%s - %s recv:\n",cp,ifp->name);
  82.         break;
  83.     case IF_TRACE_OUT:
  84.         time(&timer);
  85.         cp = ctime(&timer);
  86.         cp[24] = '\0';
  87.         fprintf(ifp->trfp,"\n%s - %s sent:\n",cp,ifp->name);
  88.         break;
  89.     }
  90.     if(bp == NULLBUF || (size = len_p(bp)) == 0){
  91.         fprintf(ifp->trfp,"empty packet!!\n");
  92.         return;
  93.     }
  94.  
  95.     if(type < NCLASS)
  96.         func = Tracef[type].tracef;
  97.     else
  98.         func = NULLVFP;
  99.  
  100.     dup_p(&tbp,bp,0,size);
  101.     if(tbp == NULLBUF){
  102.         fprintf(ifp->trfp,nospace);
  103.         return;
  104.     }
  105.     if(func != NULLVFP)
  106.         (*func)(ifp->trfp,&tbp,1);
  107.     if(ifp->trace & IF_TRACE_ASCII){
  108.         /* Dump only data portion of packet in ascii */
  109.         ascii_dump(ifp->trfp,&tbp);
  110.     } else if(ifp->trace & IF_TRACE_HEX){
  111.         /* Dump entire packet in hex/ascii */
  112.         free_p(tbp);
  113.         dup_p(&tbp,bp,0,len_p(bp));
  114.         if(tbp != NULLBUF)
  115.             hex_dump(ifp->trfp,&tbp);
  116.         else
  117.             fprintf(ifp->trfp,nospace);
  118.     }
  119.     free_p(tbp);
  120. }
  121.  
  122. /* Dump packet bytes, no interpretation */
  123. void
  124. raw_dump(ifp,direction,bp)
  125. struct iface *ifp;
  126. int direction;
  127. struct mbuf *bp;
  128. {
  129.     struct mbuf *tbp;
  130.  
  131.     /* Dump entire packet in hex/ascii */
  132.     fprintf(ifp->trfp,"\n******* raw packet dump (%s %s)\n",
  133.         ((direction & IF_TRACE_OUT) ? "send" : "recv"),ifp->name);
  134.     dup_p(&tbp,bp,0,len_p(bp));
  135.     if(tbp != NULLBUF)
  136.         hex_dump(ifp->trfp,&tbp);
  137.     else
  138.         fprintf(ifp->trfp,nospace);
  139.     fprintf(ifp->trfp,"*******\n");
  140.     free_p(tbp);
  141.     return;
  142. }
  143.  
  144. /* Dump an mbuf in hex */
  145. static void
  146. hex_dump(fp,bpp)
  147. FILE *fp;
  148. register struct mbuf **bpp;
  149. {
  150.     int16 n;
  151.     int16 address;
  152.     char buf[16];
  153.  
  154.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  155.         return;
  156.  
  157.     address = 0;
  158.     while((n = pullup(bpp,buf,sizeof(buf))) != 0){
  159.         fmtline(fp,address,buf,n);
  160.         address += n;
  161.     }
  162. }
  163. /* Dump an mbuf in ascii */
  164. static void
  165. ascii_dump(fp,bpp)
  166. FILE *fp;
  167. register struct mbuf **bpp;
  168. {
  169.     int c;
  170.     register int16 tot;
  171.  
  172.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  173.         return;
  174.  
  175.     tot = 0;
  176.     while((c = PULLCHAR(bpp)) != -1){
  177.         if((tot % 64) == 0)
  178.             fprintf(fp,"%04x  ",tot);
  179.         putc(isprint(uchar(c)) ? c : '.',fp);
  180.         if((++tot % 64) == 0)
  181.             fprintf(fp,"\n");
  182.     }
  183.     if((tot % 64) != 0)
  184.         fprintf(fp,"\n");
  185. }
  186. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  187.  * translation, e.g.,
  188.  * 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  189.  */
  190.  
  191. static void fmtline(
  192.     FILE *fp,
  193.     int16 addr,
  194.     char *buf,
  195.     int16 len )
  196. {
  197.     char line[80];
  198.     register char *aptr,*cptr;
  199.     register char c;
  200.  
  201.     memset(line,' ',sizeof(line));
  202.     ctohex(line,(int16)hibyte(addr));
  203.     ctohex(line+2,(int16)lobyte(addr));
  204.     aptr = &line[6];
  205.     cptr = &line[55];
  206.     while(len-- != 0){
  207.         c = *buf++;
  208.         ctohex(aptr,(int16)uchar(c));
  209.         aptr += 3;
  210.         c &= 0x7f;
  211.         *cptr++ = isprint(uchar(c)) ? c : '.';
  212.     }
  213.     *cptr++ = '\n';
  214.     fwrite(line,1,(unsigned)(cptr-line),fp);
  215. }
  216.  
  217. /* Convert byte to two ascii-hex characters */
  218.  
  219. static void ctohex(
  220.     char *buf,
  221.     int16 c )
  222. {
  223.     static char hex[] = "0123456789abcdef";
  224.  
  225.     *buf++ = hex[hinibble(c)];
  226.     *buf = hex[lonibble(c)];
  227. }
  228.  
  229. /* Modify or displace interface trace flags */
  230. int
  231. dotrace(argc,argv,p)
  232. int argc;
  233. char *argv[];
  234. void *p;
  235. {
  236.     struct iface *ifp;
  237.     struct tracecmd *tp;
  238.  
  239.     if(argc < 2){
  240.         for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  241.             showtrace(ifp);
  242.         return 0;
  243.     }
  244.     if((ifp = if_lookup(argv[1])) == NULLIF){
  245.         tprintf("Interface %s unknown\n",argv[1]);
  246.         return 1;
  247.     }
  248.     if(argc == 2){
  249.         showtrace(ifp);
  250.         return 0;
  251.     }
  252.     /* MODIFY THIS TO HANDLE MULTIPLE OPTIONS */
  253.     if(argc >= 3){
  254.         for(tp = Tracecmd;tp->name != NULLCHAR;tp++)
  255.             if(strncmp(tp->name,argv[2],strlen(argv[2])) == 0)
  256.                 break;
  257.         if(tp->name != NULLCHAR)
  258.             ifp->trace = (ifp->trace & ~tp->mask) | tp->val;
  259.         else
  260.             ifp->trace = htoi(argv[2]);
  261.     }
  262.     /* Always default to stdout unless trace file is given */
  263.     if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  264.         fclose(ifp->trfp);
  265.     ifp->trfp = stdout;
  266.     if(ifp->trfile != NULLCHAR)
  267.         free(ifp->trfile);
  268.     ifp->trfile = NULLCHAR;
  269.  
  270.     if(argc >= 4){
  271.         if((ifp->trfp = fopen(argv[3],APPEND_TEXT)) == NULLFILE){
  272.             tprintf("Can't write to %s\n",argv[3]);
  273.             ifp->trfp = stdout;
  274.         } else {
  275.             ifp->trfile = strdup(argv[3]);
  276.         }
  277.     }
  278.     showtrace(ifp);
  279.     return 0;
  280. }
  281. /* Display the trace flags for a particular interface */
  282. static void
  283. showtrace(ifp)
  284. register struct iface *ifp;
  285. {
  286.     if(ifp == NULLIF)
  287.         return;
  288.     tprintf("%s:",ifp->name);
  289.     if(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT | IF_TRACE_RAW)){
  290.         if(ifp->trace & IF_TRACE_IN)
  291.             tprintf(" input");
  292.         if(ifp->trace & IF_TRACE_OUT)
  293.             tprintf(" output");
  294.  
  295.         if(ifp->trace & IF_TRACE_NOBC)
  296.             tprintf(" - no broadcasts");
  297.  
  298.         if(ifp->trace & IF_TRACE_HEX)
  299.             tprintf(" (Hex/ASCII dump)");
  300.         else if(ifp->trace & IF_TRACE_ASCII)
  301.             tprintf(" (ASCII dump)");
  302.         else
  303.             tprintf(" (headers only)");
  304.  
  305.         if(ifp->trace & IF_TRACE_RAW)
  306.             tprintf(" Raw output");
  307.  
  308.         if(ifp->trfile != NULLCHAR)
  309.             tprintf(" trace file: %s",ifp->trfile);
  310.         tprintf("\n");
  311.     } else
  312.         tprintf(" tracing off\n");
  313. }
  314.  
  315. /* shut down all trace files */
  316. void
  317. shuttrace()
  318. {
  319.     struct iface *ifp;
  320.  
  321.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next){
  322.         if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  323.             fclose(ifp->trfp);
  324.         if(ifp->trfile != NULLCHAR)
  325.             free(ifp->trfile);
  326.         ifp->trfile = NULLCHAR;
  327.         ifp->trfp = NULLFILE;
  328.     }
  329. }
  330.  
  331. /* Log messages of the form
  332.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  333.  */
  334. #if    defined(ANSIPROTO)
  335. void
  336. trace_log(struct iface *ifp,char *fmt, ...)
  337. {
  338.     va_list ap;
  339.     char *cp;
  340.     long t;
  341.  
  342.     if(ifp->trfp == NULLFILE)
  343.         return;
  344.  
  345.     time(&t);
  346.     cp = ctime(&t);
  347.     rip(cp);
  348.     fprintf(ifp->trfp,"%s",cp);
  349.  
  350.     fprintf(ifp->trfp," - ");
  351.     va_start(ap,fmt);
  352.     vfprintf(ifp->trfp,fmt,ap);
  353.     va_end(ap);
  354.     fprintf(ifp->trfp,"\n");
  355. }
  356. #else
  357. /*VARARGS2*/
  358. void
  359. trace_log(ifp,fmt,arg1,arg2,arg3,arg4,arg5)
  360. struct iface *ifp;
  361. char *fmt;
  362. int arg1,arg2,arg3,arg4,arg5;
  363. {
  364.     char *cp;
  365.     long t;
  366.  
  367.     if(ifp->trfp == NULLFILE)
  368.         return;
  369.  
  370.     time(&t);
  371.     cp = ctime(&t);
  372.     rip(cp);
  373.     fprintf(ifp->trfp,"%s",cp);
  374.  
  375.     fprintf(ifp->trfp," - ");
  376.     fprintf(ifp->trfp,fmt,arg1,arg2,arg3,arg4,arg5);
  377.     fprintf(ifp->trfp,"\n");
  378. }
  379. #endif
  380.  
  381.